<template>
  <!-- 容器：固定高度，允许滚动 -->
  <div 
    ref="containerRef" 
    class="virtual-scroll-container" 
    @scroll="handleScroll"
  >
    <!-- 占位元素：模拟完整列表高度 -->
    <div 
      class="scroll-placeholder" 
      :style="{ height: `${totalHeight}px` }"
    >
      <!-- 可视区域内容：通过 translateY 动态偏移 -->
      <div 
        class="visible-items" 
        :style="{ transform: `translateY(${topOffset}px)` }"
      >
        <div 
          v-for="item in visibleItems" 
          :key="item.id" 
          class="item" 
          :style="{ height: `${itemHeight}px` }"
        >
          <!-- 通过插槽自定义渲染内容 -->
          <slot :item="item">
            {{ item.content }} <!-- 默认渲染内容 -->
          </slot>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, onMounted, withDefaults } from 'vue';

interface VirtualScrollProps {
  data: any[];          // 完整数据列表
  itemHeight: number;   // 每项固定高度（像素）
  containerHeight: number; // 容器可视高度（像素）
}

const { data, itemHeight, containerHeight } = withDefaults(defineProps<VirtualScrollProps>(), {
  data:() => [],
  itemHeight: 50, // 默认每项高度为 50px
  containerHeight: 300, // 默认容器高度为 300px
})

const containerRef = ref<HTMLElement | null>(null);
const startIndex = ref(0);

// 计算总高度（模拟完整列表）
const totalHeight = computed(() => data.length * itemHeight);

// 计算可视区域能显示的条目数
const visibleCount = computed(() => 
  Math.ceil(containerHeight / itemHeight)
);

// 截取展示的数据
const visibleItems = computed(() => 
  data.slice(
    startIndex.value, 
    startIndex.value + visibleCount.value
  )
);

// 计算显示区域与占位元素顶部的距离
const topOffset = computed(() => 
  startIndex.value * itemHeight
);

// 监听滚动
const handleScroll = () => {
  requestAnimationFrame(() => { // 使用 requestAnimationFrame 优化渲染性能，防止闪屏
    if (!containerRef.value) return;
    const scrollTop = containerRef.value.scrollTop;
    startIndex.value = Math.floor(scrollTop / itemHeight);
  });
  // const scrollTop = containerRef.value.scrollTop;
  // console.log("🚀 ~ handleScroll ~ scrollTop:", scrollTop)
  // startIndex.value = Math.floor(scrollTop / itemHeight);
};

onMounted(() => {
  if (containerRef.value) {
    containerRef.value.style.height = `${containerHeight}px`;
  }
});
</script>

<style scoped>
.virtual-scroll-container {
  overflow: auto;
  width: 100%;
  border: 1px solid #eee;
}

.scroll-placeholder {
  position: relative;
}

.visible-items {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.item {
  border-bottom: 1px solid #ddd;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  padding: 0 16px;
}
</style>